﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;

namespace ChessOnline
{
    /// <summary>
    /// Singleton. Managing authorization process in Silverlight app.
    /// </summary>
    public sealed class Authorization // sealed means no derivation
    {
        /// <summary>
        /// Stores instance of the object. Static instantination.
        /// </summary>
        private static Authorization instance = new Authorization();
        /// <summary>
        /// Stores the string of login.
        /// </summary>
        private string login = "";
        /// <summary>
        /// Stores the instance of class for managing password string.
        /// </summary>
        private PasswordManager passwordManager = new PasswordManager();
        private string sessionHash = "";
        private string isAuthorizedResult = "false";
        private bool isAuthorizationCheckEnded = false;
        private bool isAuthorizationCheckStarted = false;
        private string helloWorld = ""; // DEBUG purposes        

        private Authorization()
        {
        }        

        /// <summary>
        /// Get an instance of the Authorization object.
        /// </summary>
        /// <returns>Instance of Authorization object.</returns>
        public static Authorization Instance
        {
            get
            {
                return instance;
            }
        }

        /// <summary>
        /// This method must be called each time password box changes it's text.
        /// </summary>
        /// <param name="pwd">New password box' text.</param>
        public void PasswordStringChanged(string pwd)
        {
            if (pwd.Length > passwordManager.GetPasswordLength())
            {
                passwordManager.SymbolAdded(pwd[pwd.Length - 1]);
            }

            if (pwd.Length < passwordManager.GetPasswordLength())
            {
                passwordManager.SymbolDeleted();
            }
        }

        /// <summary>
        /// Display password in a secure way.
        /// </summary>
        /// <returns>Masked password.</returns>
        public string DisplayPassword()
        {
            return passwordManager.GetMaskedPassword();
        }

        /// <summary>
        /// Display password in a secure way.
        /// </summary>
        /// <param name="masking_symbol">Custom character for masking password.</param>
        /// <returns>Masked password.</returns>
        public string DisplayPassword(char masking_symbol)
        {
            return passwordManager.GetMaskedPassword(masking_symbol);
        }

        /// <summary>
        /// Set user login. Must be called when user finished entering login and password and wants to proceed.
        /// </summary>
        /// <param name="user_name">Login.</param>
        private void SetLogin(string user_name)
        {
            login = user_name;
        }

        private void ClearLogin()
        {
            login = "";
        }

        /// <summary>
        /// Set user password. Must be called when user finished entering login and password and wants to proceed.
        /// </summary>
        /// <param name="password">Password.</param>
        private void SetPassword(string password)
        {
            passwordManager.SetPassword(password);
        }

        private void ClearPassword()
        {
            passwordManager.ClearPassword();
        }

        /// <summary>
        /// LogIn using current credentials
        /// </summary>
        /// <param name="user_name">User name.</param>
        /// <param name="user_password">User password.</param>
        public void LogIn(string user_name, string user_password)
        {
            SetLogin(user_name);
            SetPassword(user_password);

            ChessOnlineService.ChessOnlineServiceClient cl = new ChessOnlineService.ChessOnlineServiceClient();
            cl.LogInCompleted += new EventHandler<ChessOnlineService.LogInCompletedEventArgs>(LogInCompleted);
            cl.LogInAsync(login, passwordManager.GetPassword());

            ClearLogin();
            ClearPassword();
        }

        private void LogInCompleted(object sender, ChessOnlineService.LogInCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                SetUserHash(e.Result.ToString());
                ThrowLoginEnded(sender, null);
            }
        }

        public delegate void EventHandler(object sender, object args);
        public event EventHandler ThrowLoginEnded = delegate { };

        /// <summary>
        /// Check if user with current hash is valid and logined.
        /// </summary>
        /// <returns></returns>
        public void CheckAuthorization()
        {
            ChessOnlineService.ChessOnlineServiceClient cl = new ChessOnlineService.ChessOnlineServiceClient();          
            cl.IsAuthorizedCompleted += new EventHandler<ChessOnlineService.IsAuthorizedCompletedEventArgs>(IsAuthorizationCompleted);
            cl.IsAuthorizedAsync(sessionHash);
        }

        private void IsAuthorizationCompleted(object sender, ChessOnlineService.IsAuthorizedCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                isAuthorizedResult = e.Result.ToString();
                ThrowAuthorizationCompleted(sender, null);                
            }            
        }

        public event EventHandler ThrowAuthorizationCompleted = delegate { };

        public bool IsAuthorized()
        {
            if (isAuthorizedResult == "true")
            {
                return true;
            }
            return false;
        }

        public void Register(string user_name, string user_password)
        {
            SetLogin(user_name);
            SetPassword(user_password);

            ChessOnlineService.ChessOnlineServiceClient cl = new ChessOnlineService.ChessOnlineServiceClient();
            cl.RegisterCompleted += new EventHandler<ChessOnlineService.RegisterCompletedEventArgs>(RegisterCompleted);
            cl.RegisterAsync(login, passwordManager.GetPassword());

            ClearLogin();
            ClearPassword();
        }

        void RegisterCompleted(object sender, ChessOnlineService.RegisterCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                SetUserHash(e.Result.ToString());
                ThrowRegistrationEnded(sender, sessionHash);
            }
        }

        public event EventHandler ThrowRegistrationEnded = delegate { };

        

        /// <summary>
        /// Send current session user hash.
        /// </summary>
        /// <returns>Current session user hash.</returns>
        public string GetUserHash()
        {
            return sessionHash;
        }

        public void SetCredentials(string user_name, string user_password)
        {
            SetLogin(user_name);
            SetPassword(user_password);
        }

        private void SetUserHash(string user_hash)
        {
            sessionHash = user_hash;
        }

        public bool AuthorizationCheckStarted()
        {
            return isAuthorizationCheckStarted;
        }

        public bool AuthorizationCheckEnded()
        {
            return isAuthorizationCheckEnded;
        }

        public string HelloWorld()
        {
            helloWorld = "Hello, World!";
            return helloWorld;
        }

        //public void StartCheckingForSuccessfullAuthentication(object mainPage)
        //{
        //    // Создаем побочный поток, который будет проверять завершена ли авторизация и перенаправлять
        //    // с главной страницы на верную страницу не требующую очередной авторизации.
        //    ThreadPool.QueueUserWorkItem(new WaitCallback(CheckFunction), mainPage);
        //}

        //private void CheckFunction(object objState)
        //{
        //    // Остановить исполнение потока пока не завершится получение информации при вызове авторизации.
        //    //manualResetEvent.WaitOne();
        //    //if (IsAuthorized())
        //    //{
        //    //    System.Windows.Browser.HtmlPage.Window.Navigate(new Uri("/GamesList.aspx", UriKind.Relative));
        //    //    // Снова блокировать поток до вызова следующей авторизации
        //    //    manualResetEvent.Reset();
        //    //}
        //}
    }
}
